<template>
  <div class="base-file-upload">
    <el-upload 
      :class="{ hide: !addButtonShow }" 
      ref="upload" 
      action="#" 
      :list-type="uploadOptions.listType" 
      multiple
      :auto-upload="false"
      :file-list="fileLists" 
      :limit="limit" 
      :accept="uploadOptions.accept"
      :on-remove="handleFileRemove" 
      :on-exceed="onExceed"
      :on-change="handleChange">
      <!-- 上传按钮 -->
      <i v-if="fileType === 'image'" slot="default" class="el-icon-plus"></i>
      <el-button v-else size="small" type="primary">点击上传</el-button>
      <div v-if="fileType !== 'image'" slot="tip" class="upload-tip el-upload__tip">上传文件大小不超过{{ fileSize }}MB</div>
      <!-- 上传后文件展示及工具,仅图片会展示 -->
      <div v-if="fileType === 'image'" slot="file" slot-scope="{ file }">
        <!-- 上传后图片 -->
        <el-image class="upload-img" :src="file.url" fit="cover"></el-image>
        <!-- 工具栏 -->
        <span v-if="file.url" class="el-upload-list__item-actions">
          <!-- 查看 -->
          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
            <i class="el-icon-zoom-in"></i>
          </span>
          <!-- 删除 -->
          <span class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <!-- 查看图片 -->
    <el-dialog title="查看图片" :visible.sync="seeImage" append-to-body width="800">
      <img width="100%" :src="seeImageUrl" alt="" />
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "BaseFileUpload",
  props: {
    // 数量限制
    limit: {
      type: Number,
      default: 3
    },
    // 图片大小限制，默认10MB
    fileSize: {
      type: Number,
      default: 10,
    },
    // 上传文件类型
    // image video file
    fileType: {
      type: String,
      default: 'image',
    },
    // 上传类型已做更改，如需限制具体类型，请传入后缀拼接成的字符串(用逗号隔开)
    // 例如：'.jpg,.pdf,.doc'
    // 其他类型参考
    // https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file#唯一文件类型说明符
    supportType: {
      type: String,
      default: '',
    },
    // 默认采用消息提示
    // 使用this.$message，安装了elui即可使用，解耦
    isShowTip: {
      type: Boolean,
      default: true
    },
    // 预览图片，格式为由url组成的数组
    preImgs: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      // 上传数据
      fileLists: [],
      preFileLists: [],
      seeImage: false,
      seeImageUrl: '',
    };
  },
  computed: {
    uploadOptions() {
      const options = {};
      if(this.fileType === 'image') {
        options.listType = 'picture-card';
        options.accept = 'image/*'
      } else if(this.fileType === 'video') {
        options.listType = 'text';
        options.accept = 'video/*'
      } else {
        options.listType = 'text';
        options.accept = ''
      }
      if(this.supportType) {
        options.accept = this.supportType
      }
      return options
    },
    addButtonShow() {
      let length = this.fileLists.length;
      return length < this.limit
    }
  },
  watch: {
    preImgs: {
      immediate: true,
      handler(newValue, oldValue) {
        this.fileLists = [];
        const preFileLists = newValue.map(url => {
          const random = Math.floor(Math.random () * 900) + 100;
          const time = Date.now();
          const uid = Number(random + '' + time);
          const fileName = url.slice(url.lastIndexOf('/') + 1);
          return {
            uid: uid,
            name: fileName,
            url,
          }
        })
        this.fileLists = this.fileLists.concat(preFileLists);
      },
    },
  },
  methods: {
    // 获取数据
    getFileList() {
      return this.fileLists
    },
    // 上传
    // 需要填写上传的url及响应后的地址字段
    // 返回值为url组成的数组
    async mySubmit(httpUrl, httpRes) {
      console.log('上传');
      // console.log(this.fileLists);
      let result = [];
      for(let file of this.fileLists) {
        const rawFile = file.raw;  // file对象
        if(rawFile) {  // 本地图片
          const form = new FormData();
          form.append("file", rawFile);
          let timeout = parseFloat((file.size / 1024 / 1024).toFixed(2)) * 5000;
          if (timeout < 10000) {
            // 默认时长10000
            timeout = 10000;
          }
          try {
            let res = await this.myRequestApi(httpUrl, form, timeout);
            result.push(res[httpRes])
          } catch (error) {
            break
          }
        } else {  // 网络图片
          result.push(file.url)
        }
      }
      return result
      // await this.$refs.upload.submit();  // 会触发自定义上传的钩子函数（diyRequest）
    },
    myRequestApi(url, form, timeout) {},
    // 点击查看工具
    handlePictureCardPreview(file) {
      this.seeImageUrl = file.url;
      this.seeImage = true;
    },
    // 点击删除
    handleRemove(file) {
      this.removeFile(file);
    },
    handleFileRemove(file) {
      if(this.fileType !== 'image') {
        this.removeFile(file);
      }
    },
    // 状态改变触发(将文件的校验放到这里进行处理)
    handleChange(file, files) {
      // console.log('状态改变触发file：', file);
      if(file.status === 'ready') {
        this.fileLists.push(file);  // 先放入再删除
      }
      // 只做大小检验
      const uploadError = {
        type: "",
        msg: "",
      };
      const fileSize = (file.size / 1024 / 1024).toFixed(1); // 获取图片大小（MB）
      // 图片大小出错处理
      if (Number(fileSize) > this.fileSize) {
        uploadError.type = "size error";
        uploadError.msg =
          `图片大小超出限制！上传图片大小不能超过` + this.fileSize + "MB！";
        if (this.isShowTip) {
          this.$message({
            message: uploadError.msg,
            type: 'warning'
          });
        }
        this.$emit("upload-error", uploadError);
        this.removeFile(file);
        return
      }
      // console.log('状态改变触发files：', files);
    },
    // 对fileList移除文件
    removeFile(file) {
      const uid = file.uid;
      if(uid) {
        const findFileIndex = this.fileLists.findIndex(item => {
          return item.uid === uid;
        })
        this.fileLists.splice(findFileIndex, 1)
      }
    },
    // 清空已上传的文件列表
    reset() {
      this.fileLists = [];
      this.$refs.upload.clearFiles();
    },
    // 超出个数限制
    // 如果一次性上传超出数量限制，不会触发before-upload，on-change钩子
    // files为本次超出上传的所有文件
    onExceed(files) {
      console.log('超出', files);
      const uploadError = {
        type: "",
        msg: "",
      };
      uploadError.type = "limit error";
      uploadError.msg = `超出数量限制，最多接受文件数为：` + this.limit;
      if (this.isShowTip) {
        this.$message({
          message: uploadError.msg,
          type: 'warning'
        });
      }
      this.$emit("upload-error", uploadError);
    }
  },
};
</script>

<style lang='scss' scoped>
.base-file-upload {
  .upload-img {
    width: 100%;
    height: 148px;
  }

  .hide {
    ::v-deep .el-upload--picture-card {
      display: none;
    }
  }
  
  .upload-tip {
    line-height: 20px;
  }
}
</style>
